using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using TMPro;
using UnityEngine;

namespace Super
{
	[RequireComponent(typeof(TextMeshProUGUI))]
	public class TypeWrite : MonoBehaviour, ILangRefresh
	{
		/// <summary>
		/// �Ӵ֣���б����ɫ����С, ����, �»���,��β��
		/// </summary>
		private List<string> richFormats = new List<string>() { "<b>", "<i>", "<color", "<size", "<link", "<u>", "</" };
		private char richEndSign = '>';
		private TextMeshProUGUI TMP_text;
		private TextMeshProUGUI TMP_Text
		{
			get
			{
				if (TMP_text == null)
				{
					TMP_text = GetComponent<TextMeshProUGUI>();
				}
				return TMP_text;
			}
		}
		private string typerText;
		private IEnumerator typerIterator;
		private TypeWriteState typerState = TypeWriteState.UnStart;
		private Action callBack;

		private string key = "";
		private List<object> args = new List<object>();

		/// <summary>
		/// ��ȡ��ӡ��״̬
		/// </summary>
		/// <returns></returns>
		public TypeWriteState GetTyperState()
		{
			return typerState;
		}

		/// <summary>
		/// ��ʼ��ӡ�ı�
		/// </summary>
		/// <param name="text"></param>
		/// <param name="params_interval"></param>
		private void StartTypingText(string text)
		{
			CancelTypingText();
			this.typerText = text;
			typerIterator = TypingCo();
			StartCoroutine(typerIterator);
			typerState = TypeWriteState.Doing;
		}

		/// <summary>
		/// ��ӡ����Ҫ����Ķ������ֵȣ���Ҫ��ӡ�ı�����Ӱ������Թ���
		/// </summary>
		/// <param name="obj"></param>
		public void StartTyping(object obj)
		{
			CancelTypingText();
			key = "";
			this.typerText = obj.ToString();
			typerIterator = TypingCo();
			StartCoroutine(typerIterator);
			typerState = TypeWriteState.Doing;
		}

		/// <summary>
		/// ��ӡ������
		/// </summary>
		/// <param name="key"></param>
		public void StartTypingByKey(string key)
		{
			List<object> list = new List<object>();
			StartFormatTyping(key, list);
		}

		/// <summary>
		/// ��ӡ��ʽ��������
		/// </summary>
		/// <param name="key"></param>
		/// <param name="arg0"></param>
		public void StartFormatTyping(string key, object arg0)
		{
			List<object> list = new List<object>() { arg0 };
			StartFormatTyping(key, list);
		}

		public void StartFormatTyping(string key, object arg0, object arg1)
		{
			List<object> list = new List<object>() { arg0 , arg1 };
			StartFormatTyping(key, list);
		}

		public void StartFormatTyping(string key, object arg0, object arg1, object arg2)
		{
			List<object> list = new List<object>() { arg0, arg1 , arg2 };
			StartFormatTyping(key, list);
		}

		public void StartFormatTyping(string key, List<object> args)
		{
			string content = LangManager.GetText(key);
			content = string.Format(content, args);
			this.key = key;
			this.args = args;
			StartTypingText(content);
		}

		/// <summary>
		/// ˢ�¶������ı�
		/// </summary>
		public void OnLangRefresh()
		{
			if (!string.IsNullOrEmpty(key))
			{
				ForceFinishTypingText();
				string content = LangManager.GetText(key);
				content = string.Format(content, args);
				typerText = content;
				TMP_Text.text = content;
			}
		}

		/// <summary>
		/// ������ɴ����ص�
		/// </summary>
		public void OnFinishTyping()
		{
			typerState = TypeWriteState.Finish;
			TMP_Text.text = typerText;
			callBack?.Invoke();
		}

		/// <summary>
		/// ȡ����ӡ�ı�
		/// </summary>
		public void CancelTypingText()
		{
			if (typerIterator != null)
			{
				StopCoroutine(typerIterator);
			}
		}

		/// <summary>
		/// ǿ����ɴ�ӡ�ı�
		/// </summary>
		public void ForceFinishTypingText()
		{
			if (GetTyperState() == TypeWriteState.Finish)
			{
				return;
			}
			CancelTypingText();
			OnFinishTyping();
		}

		/// <summary>
		/// ���ý����ص�
		/// </summary>
		/// <param name="action"></param>
		public void SetFinishCallBack(Action action)
		{
			callBack = action;
		}

		/// <summary>
		///�����첽����
		/// </summary>
		/// <returns></returns>
		private IEnumerator TypingCo()
		{
			int tempIndex = 0, subWordsLen = 0;
			string subWords = "";
			StringBuilder SB = new StringBuilder();

			for (int i = 0; i < typerText.Length;)
			{
				bool isRich = CheckIsRichText(typerText, i);
				tempIndex = i + 1;
				while (isRich)
				{
					tempIndex = GetRichEndIndex(typerText, tempIndex);
					tempIndex += 1;
					isRich = CheckIsRichText(typerText, tempIndex);
				}

				subWordsLen = tempIndex - i;
				subWords = typerText.Substring(i, subWordsLen);
				SB.Append(subWords);
				TMP_Text.text = SB.ToString();
				yield return new WaitForSeconds(FWConfig.typerInterval);
				i += subWordsLen;
			}
			OnFinishTyping();
		}

		/// <summary>
		/// ��index������ʼ���Ƿ��Ǹ��ı�
		/// </summary>
		/// <param name="words">����ı�</param>
		/// <param name="index">��⿪ʼ������</param>
		/// <returns></returns>
		private bool CheckIsRichText(string words, int index)
		{
			if (index >= words.Length - 1)
				return false;

			string subString = words.Substring(index);
			foreach (var item in richFormats)
			{
				if (subString.StartsWith(item))
					return true;
			}
			return false;
		}

		/// <summary>
		/// ���ظ��ı��������±�
		/// </summary>
		/// <param name="words">����ı�</param>
		/// <param name="index">��⿪ʼ������</param>
		/// <returns></returns>
		private int GetRichEndIndex(string words, int index)
		{
			for (int i = index; i < words.Length; i++)
			{
				if (words[i] == richEndSign)
					return i;
			}
			return index;
		}
	}

}
